using Engine;
using Engine.Graphics;

namespace RuthlessConquest {
    public class ParticleSystem<T> : ParticleSystemBase where T : Particle, new() {
        public Texture2D publicTexture;

        public TexturedBatch2D AdditiveBatch;

        public TexturedBatch2D AlphaBlendedBatch;

        public T[] Particles { get; }

        public Texture2D Texture {
            get => publicTexture;
            set {
                if (value != publicTexture) {
                    publicTexture = value;
                    AdditiveBatch = null;
                    AlphaBlendedBatch = null;
                }
            }
        }

        public int TextureSlotsCount { get; set; }

        public ParticleSystem(int particlesCount, int layer) {
            Layer = layer;
            Particles = new T[particlesCount];
            for (int i = 0; i < Particles.Length; i++) {
                Particles[i] = new T();
            }
        }

        public override void Draw(CameraModule cameraModule, Color colorTransform) {
            if (AdditiveBatch == null
                || AlphaBlendedBatch == null) {
                AdditiveBatch = cameraModule.PrimitivesRenderer.TexturedBatch(
                    publicTexture,
                    true,
                    0,
                    null,
                    null,
                    BlendState.Additive,
                    SamplerState.LinearClamp
                );
                AlphaBlendedBatch = cameraModule.PrimitivesRenderer.TexturedBatch(
                    publicTexture,
                    true,
                    0,
                    null,
                    null,
                    BlendState.AlphaBlend,
                    SamplerState.LinearClamp
                );
            }
            float num = 1f / TextureSlotsCount;
            for (int i = 0; i < Particles.Length; i++) {
                Particle particle = Particles[i];
                if (particle.IsActive) {
                    Vector2 position = particle.Position;
                    Vector2 size = particle.Size;
                    float rotation = particle.Rotation;
                    int textureSlot = particle.TextureSlot;
                    Vector2 p;
                    Vector2 p2;
                    Vector2 p3;
                    Vector2 p4;
                    if (rotation != 0f) {
                        Vector2 vector = new(MathUtils.Cos(rotation), MathUtils.Sin(rotation));
                        Vector2 vector2 = Vector2.Perpendicular(vector);
                        vector2 *= size.Y;
                        vector *= size.X;
                        p = position + (-vector2 - vector);
                        p2 = position + (vector2 - vector);
                        p3 = position + (vector2 + vector);
                        p4 = position + (-vector2 + vector);
                    }
                    else {
                        Vector2 vector3 = Vector2.UnitX * size.X;
                        Vector2 vector4 = Vector2.UnitY * size.Y;
                        p = position + (-vector3 - vector4);
                        p2 = position + (vector3 - vector4);
                        p3 = position + (vector3 + vector4);
                        p4 = position + (-vector3 + vector4);
                    }
                    TexturedBatch2D obj = particle.UseAdditiveBlending ? AdditiveBatch : AlphaBlendedBatch;
                    Vector2 vector5 = new(textureSlot % TextureSlotsCount, textureSlot / TextureSlotsCount);
                    float num2 = 0f;
                    float num3 = 1f;
                    float num4 = 1f;
                    float num5 = 0f;
                    if (particle.FlipX) {
                        num2 = 1f - num2;
                        num3 = 1f - num3;
                    }
                    if (particle.FlipY) {
                        num4 = 1f - num4;
                        num5 = 1f - num5;
                    }
                    Vector2 texCoord = (vector5 + new Vector2(num2, num4)) * num;
                    Vector2 texCoord2 = (vector5 + new Vector2(num3, num4)) * num;
                    Vector2 texCoord3 = (vector5 + new Vector2(num3, num5)) * num;
                    Vector2 texCoord4 = (vector5 + new Vector2(num2, num5)) * num;
                    obj.QueueQuad(
                        p,
                        p2,
                        p3,
                        p4,
                        0f,
                        texCoord,
                        texCoord2,
                        texCoord3,
                        texCoord4,
                        colorTransform == Color.White ? particle.Color : particle.Color * colorTransform
                    );
                }
            }
        }

        public override bool Run(float dt) => false;
    }
}